package cn.xuqiudong.sso.server.service;

import cn.xuqiudong.sso.server.config.SsoConfiguration;
import cn.xuqiudong.sso.server.model.AppClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 描述: 配置的客户端service, 当前表的数据暂时直接db操作
 * @author Vic.xu
 * @since 2022-05-17 10:02
 */
@Service
public class ClientConfigService {

    private static final Logger logger = LoggerFactory.getLogger(ClientConfigService.class);

    /**
     * 每5分钟更新一次数据库里的sso client列表到配置信息中
     */
    private static final long FIXED_DELAY_SECOND = 5 * 60;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    public SsoConfiguration ssoConfiguration;

    /**
     * 自动更新配置中的数据库里的sso client列表
     */
    @Scheduled(initialDelay = FIXED_DELAY_SECOND, fixedDelay = FIXED_DELAY_SECOND, timeUnit = TimeUnit.SECONDS)
    public void updateClientsConfigSchedule() {
        logger.info("自动更新数据库里的sso client列表到配置信息中");
        updateClientsConfig();
    }

    /**
     * 把数据库查询出来的sso客户端配置存到SsoConfiguration中
     */
    @PostConstruct
    private void initAllClient() {
        updateClientsConfig();
        if (ssoConfiguration.getClientMap().isEmpty()) {
            throw new IllegalStateException("尚未配置可用的sso客户端， 请前往配置文件或数据库配置 clients");
        }
        String clients = String.join(", ", ssoConfiguration.getClientMap().keySet());
        logger.info("初始化全部的sso 客户端； 数量为{}, clients = {}", ssoConfiguration.getClientMap().size(), clients);
    }

    private static final String SELECT_SQL = "SELECT a.app_id AS id, a.group, a.secret, a.logout_url AS logoutUrl FROM client_config a WHERE a.enabled = 1 ";

    /**
     * 查询所有的客户端, 不会return  null
     * @return all client list
     */
    public List<AppClient> allClients() {
        return jdbcTemplate.query(SELECT_SQL, new BeanPropertyRowMapper<AppClient>(AppClient.class));
    }

    /**
     * 更新当前配置中的可用客户端列表:
     * 1. 从配置文件中读取的 不动，
     * 2. 从数据库读取的重新加载
     */
    public void updateClientsConfig() {

        //把配置的客户端读出来
        List<AppClient> configClients = new ArrayList<>(ssoConfiguration.getClients());
        //数据库配置的客户端
        List<AppClient> appClients = allClients();
        configClients.addAll(appClients);

        Map<String, AppClient> collect = configClients.stream().collect(Collectors.toMap(AppClient::getId, c -> c, (v1, v2) -> v1));
        //更新ssoConfiguration 中的clientMap
        ssoConfiguration.setClientMap(collect);
    }
}
